import Fuse from 'fuse.js';
import YAML from 'yaml';
import { create } from 'zustand';
import { Lib, LibResult } from './Lib.interfaces';

const fuse = new Fuse<Lib>([], {
  minMatchCharLength: 2,
  includeMatches: true,
  includeScore: true,
  useExtendedSearch: true,
  keys: ['name', 'tags', 'lang', 'desc'],
});

function search(query: string, libs: Lib[]) {
  const _query = query.trim();
  let results: LibResult[] = [];
  if (_query) {
    results = fuse.search(_query);
  }
  if (!results.length) {
    results = libs.map((item, refIndex) => ({ item, refIndex }));
  }
  return results;
}

function getPagedData<T = any>(data: T[], page: number, size: number) {
  const start = (page - 1) * size;
  const end = page * size;
  return data.slice(start, end);
}

// function delay(ms: number) {
//   return new Promise((resolve) => setTimeout(resolve, ms));
// }

interface LibStore {
  pending: boolean;
  allLibs: Lib[];
  query: string;
  filteredLibs: LibResult[];
  libs: LibResult[];
  total: number;
  page: number;
  size: number;
  load(): Promise<void>;
  setQuery(text: string): void;
  setPage(page: number): void;
}

export const useLibStore = create<LibStore>((set, get) => {
  return {
    pending: false,
    allLibs: [],
    query: '',
    filteredLibs: [],
    libs: [],
    total: 0,
    page: 1,
    size: 10,
    async load() {
      set({ pending: true });
      try {
        const res = await fetch(process.env.PUBLIC_URL + '/data.yaml');
        // gitee pages will response /index.html with status 200 if file not exists
        // if (res.status >= 400) {
        //   throw new Error(`[${res.status}] load data failed.`);
        // }
        const yaml = await res.text();
        const data = YAML.parse(yaml);
        if (!data || !data.libs) {
          throw new Error('load data failed.');
        }
        const allLibs = data.libs;
        const { query, size } = get();
        fuse.setCollection(allLibs);
        const filteredLibs = search(query, allLibs);
        const page = 1;
        const total = filteredLibs.length;
        const libs = getPagedData(filteredLibs, page, size);
        set({ allLibs, filteredLibs, page, libs, total });
        // await delay(1000);
      } finally {
        set({ pending: false });
      }
    },
    setQuery(text) {
      const { allLibs, size } = get();
      const filteredLibs = search(text, allLibs);
      const page = 1;
      const total = filteredLibs.length;
      const libs = getPagedData(filteredLibs, page, size);
      set({ query: text, filteredLibs, page, libs, total });
    },
    setPage(page) {
      const { filteredLibs, size } = get();
      const libs = getPagedData(filteredLibs, page, size);
      set({ page, libs });
    },
  };
});
